/****************************************************************************
 * Included Files
 ****************************************************************************/

#include "ad7708.h"
#include "bsp.h"
#include "stdio.h"
#include "stdlib.h"
#include "los_sys.h"
#include "los_task.h"

uint8_t IsLong[16]={0,0,0,0,1,1,1,0,0,0,0,0,1,1,0,0};

void ADC7708_RST(void)
{
	AD7708_RST_L;
	LOS_TaskDelay(10);
	AD7708_RST_H;
}

/****************************************************************************
 * Name: ad7708_write_reg
 *
 * Description:
 *    Write to the registers starting with the register address specified as
 *    part of the instruction. The number of registers that will be written
 *    is one plus the value of the second byte.
 *
 ****************************************************************************/
HAL_StatusTypeDef ad7708_write_reg(uint8_t const reg_addr, uint16_t const reg_value)
{
	HAL_StatusTypeDef status;

	status = USR_SPI_WriteByte(USR_SPI1,reg_addr);
	if(IsLong[reg_addr])
	{
		if(status == HAL_OK)
			status = USR_SPI_WriteByte(USR_SPI1,(uint8_t)(reg_value>>8));
	}
	if(status == HAL_OK)
		status = USR_SPI_WriteByte(USR_SPI1,(uint8_t)reg_value);
	return status;
}
/****************************************************************************
 * Name: ad7708_read_reg
 *
 * Description:
 *   Output the data from up to 16 registers starting with the register
 *   address specified as part of the instruction.  The number of registers
 *   read will be one plus the second byte count. If the count exceeds the
 *   remaining registers, the addresses wrap back to the beginning.
 *
 ****************************************************************************/
void ad7708_read_reg(uint8_t const reg_addr, uint16_t *reg_value)
{
	uint8_t h=0,l=0;

	USR_SPI_WriteByte(USR_SPI1,reg_addr|0x40);
	if(IsLong[reg_addr])
	{
		h = USR_SPI_ReadWriteByte(USR_SPI1,0xff);
	}
	l = USR_SPI_ReadWriteByte(USR_SPI1,0xff);
	*reg_value = ((h<<8)&0xff00)|l;
}

/****************************************************************************
 * Name: ad7708_read_conversion_result
 ****************************************************************************/
void ad7708_read_conversion_result(uint16_t *conversion_result)
{
	ad7708_read_reg(AD7708_REG_ADC_DATA,conversion_result);
}
/****************************************************************************
 * Name: ad7708_set_adccon
 channel:0-7
 ****************************************************************************/
void ad7708_set_adccon(uint8_t adccon)
{
  ad7708_write_reg(AD7708_REG_ADC_CON,adccon);
}
/****************************************************************************
 * Name: ad7708_set_mode
 mode:MD2:0
 ****************************************************************************/
void ad7708_set_mode(enum AD7708_MODE_e mode)
{
  uint8_t tempmode = 0x40|mode;
  ad7708_write_reg(AD7708_REG_MODE,tempmode);
}
/****************************************************************************
 * Name: ad7708_set_filter
 filter: 13-255 chop enable
         3-255 chop disable
 ****************************************************************************/
void ad7708_set_filter(uint8_t ft)
{
  ad7708_write_reg(AD7708_REG_FILTER,ft);
}
/****************************************************************************
 * Name: ad7708_set_gain
 ****************************************************************************/
void ad7708_set_gain(uint16_t gain)
{
  ad7708_write_reg(AD7708_REG_ADC_GAIN,gain);
}
/****************************************************************************
 * Name: ad7708_InternalCalibration
 ****************************************************************************/
void ad7708_InternalCalibration(void)
{
	uint8_t ch;
	uint16_t temp;
	for(ch = 0;ch < 4;ch++)//7708 4 differential input channels
	{
		ad7708_write_reg(AD7708_REG_ADC_CON,AD7708_REG_ADC_CON_DEFAULT|(ch<<4));
		ad7708_write_reg(AD7708_REG_MODE,AD7708_REG_MODE_DEFAULT|0x04);//internal zero-scale
		do
		{
			ad7708_read_reg(AD7708_REG_MODE,&temp);
			temp &= 0x07;
		}
		while(temp!=0x01);//wait cal finish
		ad7708_write_reg(AD7708_REG_MODE,AD7708_REG_MODE_DEFAULT|0x05);//internal full-scale
		do
		{
			ad7708_read_reg(AD7708_REG_MODE,&temp);
			temp &= 0x07;
		}
		while(temp!=0x01);//wait cal finish
	}
}
/****************************************************************************
 * Name: ad7708_is_data_ready
 ****************************************************************************/
uint8_t ad7708_is_data_ready(void)
{
	uint16_t acr_reg_value = 0xFF;

	ad7708_read_reg(AD7708_REG_STATUS, &acr_reg_value);
	return (uint8_t)(acr_reg_value & AD7708_REG_STATUS_BIT_RDY);
}
void ad7708_Init(void)
{
	ADC7708_RST();
	AD7708_CS_L;
	USR_SPI_SetSpeed(USR_SPI1,SPI_BAUDRATEPRESCALER_8); //设置为45M时钟,高速模式
	ad7708_write_reg(AD7708_REG_MODE,AD7708_REG_MODE_DEFAULT);
	ad7708_write_reg(AD7708_REG_ADC_CON,AD7708_REG_ADC_CON_DEFAULT);
	ad7708_InternalCalibration();
}
uint16_t ad7708_read_value(AD7708_CHANNEL_E channe_num)
{
	uint8_t 	dataready = 0;
	uint16_t 	adc_value;
	uint32_t 	uwcyclePerTick,uwcyclePerTick1;
	switch(channe_num)
	{
		case USR_CHANNEL1:
			ad7708_set_adccon(ADCCH_AIN1_COM|UNIPOLAR|ADC_RN_7);
		break;
		case USR_CHANNEL2:
			ad7708_set_adccon(ADCCH_AIN2_COM|UNIPOLAR|ADC_RN_7);
		break;
		case USR_CHANNEL3:
			ad7708_set_adccon(ADCCH_AIN3_COM|UNIPOLAR|ADC_RN_7);
		break;
		case USR_CHANNEL4:
			ad7708_set_adccon(ADCCH_AIN4_COM|UNIPOLAR|ADC_RN_7);
			
		break;
		default:
		break;
	}
	ad7708_set_mode(AD7708_MODE_SINGLE_CONV);
	uwcyclePerTick = LOS_CyclePerTickGet();
	do{
		dataready = ad7708_is_data_ready();
		uwcyclePerTick1 = LOS_CyclePerTickGet();
		if(abs(uwcyclePerTick1 -uwcyclePerTick) >= 1000)
		{
			ADC7708_RST();
			ad7708_Init();
		}
	}
	while(!dataready);
	ad7708_read_conversion_result(&adc_value);
	return adc_value;
}

